#include<mysql/mysql.h>
#include<mutex>
#include<jsoncpp/json/json.h>
#include<iostream>
#include<fstream>
#include<stdio.h>
using namespace std;

namespace vod_system
{
#define MYSQL_HOST "127.0.0.1"
#define MYSQL_USR "root"
#define MYSQL_PASS "1"
#define MYSQL_NAME "vod_system"
  static MYSQL* MysqlInit(MYSQL* mysql){
    mysql = mysql_init(NULL);
    if(mysql == NULL)
    {
      cout<<"mysql init error"<<endl;
      return NULL;
    }
    if(mysql_real_connect(mysql,MYSQL_HOST,MYSQL_USR,MYSQL_PASS,MYSQL_NAME,0,NULL,0) == NULL)
    {
      cout<<mysql_error(mysql)<<endl;
      return NULL;
    }
    if(mysql_set_character_set(mysql,"utf8")!=0)
    {
      cout<<mysql_error(mysql)<<endl;
      return NULL;
    }
    return mysql;
  }
  static void MysqlRelease(MYSQL* mysql)
  {
    if(mysql != NULL)
    {
      mysql_close(mysql);
    }
    return;
  }
  static bool MysqlQuery(MYSQL* mysql, const string& sql)
  {
    int ret = mysql_query(mysql,sql.c_str());
    if(ret != 0)
    {
      cout<<sql<<endl;
      cout<<mysql_error(mysql)<<endl;
      return false;
    }
    return true;
  }
  class TableVod{
  public:
      TableVod()
      {
        //mysql句柄初始化、连接服务器、设置字符集
        _mysql = MysqlInit(_mysql);
        if(_mysql == NULL){
        exit(0);
        }
      }
      ~TableVod()
      {
        //mysql句柄销毁
        MysqlRelease(_mysql);
      }
      bool Insert(const Json::Value& video)//输入参数，不希望被修改
      {
        char sql[4096] ={0};
#define VIDEO_INSERT "insert tb_vedio Values(null,'%s','%s','%s','%s',now());"
        sprintf(sql,VIDEO_INSERT,video["name"].asCString(),video["vdes"].asCString(),
                              video["vedio_url"].asCString(),video["image_url"].asCString());
        return MysqlQuery(_mysql,sql);
      }
      bool Delete(int video_id)
      {
        char sql[4096] = {0};
#define VEDIO_DELETE "delete from tb_vedio where id=%d;"
        sprintf(sql,VEDIO_DELETE,video_id);
        return MysqlQuery(_mysql,sql);
      }
      bool Update(int video_id,const Json::Value& video)
      {
        char sql[4096] = {0};
#define VEDIO_UPDATE "update tb_vedio set name='%s',vdes='%s',vedio_url='%s',image_url='%s' where id=%d;"
        sprintf(sql,VEDIO_UPDATE,video["name"].asCString(),video["vdes"].asCString(),
                      video["vedio_url"].asCString(),video["image_url"].asCString(),video_id);
        return MysqlQuery(_mysql,sql);
      }
      bool SelectOne(int video_id,Json::Value* video)//输出参数,返回一段地址
      {
#define VEDIO_GETONE "select * from tb_vedio where id =%d;"
        char sql[4096] = {0};
        sprintf(sql,VEDIO_GETONE,video_id);
        _mutex.lock();
        bool ret = MysqlQuery(_mysql,sql);
        if(ret == false)
        {
          _mutex.unlock();
          return false;
        }
        //保存查询结果集
        MYSQL_RES* res = mysql_store_result(_mysql);
        _mutex.unlock();
        if(res == NULL)
        {
          cout<<"store result error"<<endl;
          return false;
        }
        int num_row = mysql_num_rows(res);
        if(num_row != 1)
        {
          cout<<"Condition query error"<<endl;
          //查询失败保存的本地结果集就没有存在的必要了
          mysql_free_result(res);
          return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        (*video)["id"]=video_id;
        (*video)["name"] = row[1];
        (*video)["vdes"] = row[2];
        (*video)["vedio_url"] = row[3];
        (*video)["image_url"] = row[4];
        (*video)["ctime"] = row[5];

        return true;
        
      }

      bool SelectAll(Json::Value* video)
      {
#define VEDIO_GETALL "select * from tb_vedio;"
        _mutex.lock();
        bool ret = MysqlQuery(_mysql,VEDIO_GETALL);
        if(ret == false)
        {
          _mutex.unlock();
          return false;
        }
        MYSQL_RES* res = mysql_store_result(_mysql);
        _mutex.unlock();
        if(res == NULL)
        {
          cout<<"store result failed\n";
          return false;
        }
        int num = mysql_num_rows(res);
        for(int i =0;i<num;i++)
        {
          MYSQL_ROW row = mysql_fetch_row(res);
          Json::Value val;
          val["id"] = stoi(row[0]);
          val["name"] = row[1];
          val["vdes"] = row[2];
          val["vedio_url"] = row[3];
          val["image_url"] = row[4];
          val["ctime"] = row[5];
          video->append(val);
        }
        mysql_free_result(res);
        return true;
      }
  private:
      MYSQL* _mysql;
      std::mutex _mutex; 
  };



  //使用工具类
  class Util
  {
    public:
    //提供一个接口，将文件内容content写入到对应的文件name中
    static bool WriteFile(const string& name,const string& content)
    {
      ofstream of;
      of.open(name, ios::trunc);
      if(!of.is_open())
      {
        return false;
      }
      of.write(content.c_str(),content.size());
      //of.good()表示上一个io操作是正常的
      if(!of.good())
      {
        cout<<"write file failed"<<endl;
        return false;
      }
      of.close();
      return true;
    }
  };


} //namespace vod_system
